package Harmonisation.Voix;

import java.util.ArrayList;

import javax.sound.midi.*;

import Harmonisation.Note;

public abstract class Voix {
	@SuppressWarnings({ "unused" })
	private static int noteMin, noteMax;
	protected ArrayList<Note> partition;
	private static final int VELOCITY = 64;
	int canal;

	public Voix(ArrayList<Note> partition) {
		this.partition = partition;
	}

	public void ajouterNote(String note, int temps) {
		Note n = new Note(note, temps);
		partition.add(n);
	}

	/**
	 * Renvois le lylipond correspondant à une voix
	 * 
	 * @param voix
	 *            Le nom de la voix (Basse, Tenor, Alto ou Soprano)
	 * @return
	 */
	public abstract String lilypond();

	/**
	 * Renvois la track midi d'une voix
	 * 
	 * @param sequence
	 * @return
	 */
	public Track trackMidi(Sequence sequence, int instrument) {
		Track track = sequence.createTrack();

		try {
			track.add(instrument(instrument, canal)); // flute
			int cptTick = 0;
			for (Note note : partition) {
				track.add(noteOn(note.getMidi(), cptTick, canal));
				cptTick += note.getTemps();
				track.add(noteOff(note.getMidi(), cptTick, canal));
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return track;
	}

	private static MidiEvent noteOn(int nKey, long lTick, int canal) throws InvalidMidiDataException {
		return createNoteEvent(ShortMessage.NOTE_ON, nKey, VELOCITY, lTick, canal);
	}

	private static MidiEvent noteOff(int nKey, long lTick, int canal) throws InvalidMidiDataException {
		return createNoteEvent(ShortMessage.NOTE_OFF, nKey, 0, lTick, canal);
	}

	private static MidiEvent instrument(int instrument, int canal) throws InvalidMidiDataException {
		return createNoteEvent(ShortMessage.PROGRAM_CHANGE, instrument, 0, 0, canal);
	}

	private static MidiEvent createNoteEvent(int nCommand, int nKey, int nVelocity, long lTick, int canal) throws InvalidMidiDataException {
		ShortMessage message = new ShortMessage();
		message.setMessage(nCommand, canal, nKey, nVelocity);
		return new MidiEvent(message, lTick);
	}

	public String toString() {
		String s = "";
		s += partition;
		return s;
	}

	public ArrayList<Note> getPartition() {
		return partition;
	}

	public void setPartition(ArrayList<Note> partition) {
		this.partition = partition;
	}

}
